/*
 
    1. 状态初始化:组件开始时，它会初始化一些状态变量，如 chatList（用于存储聊天消息列表）、
     message（用于存储用户在文本框中输入的消息）、socketRef（用于存储 WebSocket 实例的引用）等
 
    2. 建立 WebSocket 连接:在 useEffect 钩子中，组件会建立 WebSocket 连接到服务器。它使用 io 函数从服务器获取 WebSocket 实例，
    并传递了一些参数，如服务器地址和令牌等。 一旦连接建立成功，服务器会发送一个 connect 事件，触发回调函数向用户打个招呼，并初始化聊天消息列表
 
    3. 接收消息：在建立连接后，组件会监听来自服务器的 message 事件。当服务器发送消息时，这个事件会触发回调函数，
    将接收到的消息添加到 chatList 中，以便在页面上显示
 
    4. 发送消息：用户在文本框中输入消息后，点击发送按钮时，sendMessage 函数会被调用。它首先将消息添加到本地的 chatList 中，
    然后使用 WebSocket 实例发送消息给服务器。 发送完消息后，文本框会被清空以便用户输入新的消息

    5. 页面渲染：根据 chatList 中的消息列表，页面会动态地渲染出聊天内容，显示用户和机器人之间的对话。每个消息都会根据其类型显示不同的样式和头像
 
    6. 清理：当组件被卸载时，useEffect 返回的清理函数会被调用。这个清理函数关闭 WebSocket 连接，以避免内存泄漏和不必要的网络请求
  */

import Header from "@/shared/header";
import Back from "@/shared/back";
import Icon from "@/components/icon";
import styles from "./index.module.scss";
import { io, Socket } from "socket.io-client";
import { useEffect, useRef, useState } from "react";
import { getToken } from "@/utils/token";
import classNames from "classnames";

type Chat = {
  message: string;
  type: "user" | "xz" | "robot";
};

export default function Chat() {
  const [chatList, setChatList] = useState<Chat[]>([]);
  // 用于保存 socket 实例对象的引用
  const socketRef = useRef<Socket | null>(null);
  // 用于存储用户在文本框中输入的内容
  const [message, setMessage] = useState("");

  // 用于保存滚动容器 DOM 对象
  const scrollContainer = useRef<HTMLUListElement | null>(null);

  useEffect(() => {
    // 1.建立连接
    const socketio = io("http://toutiao.itheima.net", {
      // 参数
      query: {
        token: getToken().token,
      },
      // 连接方式
      transports: ["websocket"],
    });
    // 2.连接成功
    socketio.on("connect", () => {
      // 让小智给打个招呼
      setChatList([
        { message: "你好，我是小坤", type: "xz" },
        { message: "哥哥有什么疑问？", type: "xz" },
      ]);
    });
    // 接收服务器返回的消息
    // 保存 socket 实例对象
    socketRef.current = socketio;
    // 监听服务端响应信息
    socketio.on("message", (response) => {
      // 将消息添加到本地消息列表
      setChatList((messages) => [
        ...messages,
        { type: "robot", message: response.msg },
      ]);
    });
    if (scrollContainer.current === null) return;
    scrollContainer.current.scrollTo({
      top: scrollContainer.current.scrollHeight,
      behavior: "smooth",
    });

    // 返回清理函数
    return () => {
      // 在组件销毁时关闭 socket 连接
      if (socketRef.current) {
        socketRef.current.close();
      }
    };
  }, []);

  // 发送消息
  const sendMessage = () => {
    // 将消息添加到本地消息列表
    setChatList([...chatList, { type: "user", message }]);
    // 向服务器端发送消息
    if (socketRef.current) {
      socketRef.current.emit("message", {
        msg: message,
        timestamp: Date.now() + "",
      });
    }
    // 清空文本框中的消息
    setMessage("");
  };

  return (
    <div className={styles.chat}>
      {/* 头部 */}
      <Header title={"小智同学"} left={<Back />} />
      {/* 聊天内容展示区域 */}
      <ul className={styles.content} ref={scrollContainer}>
        {chatList.map((item, index) => (
          <li
            key={index}
            // 根据消息类型添加不同的样式类
            className={classNames({ [styles.customer]: item.type === "user" })}
          >
            <div className={styles.avatar}>
              {/* 根据消息类型展示不同的头像 */}
              {item.type === "robot" ? (
                <Icon type={"iconbtn_xiaozhitongxue"} />
              ) : (
                <img
                  src={
                    "https://b0.bdstatic.com/3392572631e1aa82b0374750aa0fdb62.jpg@h_1280"
                  }
                  alt={""}
                />
              )}
            </div>
            <div className={styles.say}>{item.message}</div>
          </li>
        ))}
      </ul>
      {/* 底部编辑区域 */}
      <div className={styles.footer}>
        <div className={styles.edit}>
          <Icon type={"iconbianji"} />
          <input
            type="text"
            placeholder="请描述你的问题"
            value={message}
            onChange={(event) => setMessage(event.target.value)}
          />
        </div>
        {/* 发送按钮 */}
        <button
          style={{
            backgroundColor: "#fff",
            color: "#bbb",
            padding: "10px 20px",
            border: "none",
            borderRadius: "5px",
          }}
          onClick={sendMessage}
        >
          发送
        </button>
      </div>
    </div>
  );
}
